package com.facebook.android;

/*
 * The me, delete and back_parent buttons are downloaded from http://icongal.com/
 */

import java.util.Iterator;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.text.util.Linkify;
import android.text.util.Linkify.TransformFilter;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.Toast;

public class GraphExplorer extends Activity {
	private Button mSubmitButton, mViewURLButton;
	private Button mGetPermissionsButton;
	private Button mTextDeleteButton, mMeButton;
	private Button mFieldsConnectionsButton, mBackParentButton;
	private TextView mOutput;
	private EditText mInputId;
	private Bundle params;
	private String url, mParentObjectId;
	private ProgressDialog dialog;
	private String rootString;
	private ScrollView mScrollView;
	private Handler mHandler;
	private final String BASE_GRAPH_URL = "https://graph.facebook.com";
	
	private JSONObject metadataObject;
	
	/*
	 * Layout the Graph Explorer
	 */
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		mHandler = new Handler();
		
		setContentView(R.layout.graph_explorer);
		
		url = BASE_GRAPH_URL; //Base URL
		
		mInputId = (EditText) findViewById(R.id.inputId);
		mOutput = (TextView) findViewById(R.id.output);
		mSubmitButton = (Button) findViewById(R.id.submitButton);
		mViewURLButton = (Button) findViewById(R.id.viewURLButton);
		mGetPermissionsButton = (Button) findViewById(R.id.accessTokenButton);
		mFieldsConnectionsButton = (Button) findViewById(R.id.fieldsAndConnectionsButton);
		mBackParentButton = (Button) findViewById(R.id.backParentButton);
		
		mScrollView = (ScrollView) findViewById(R.id.ScrollView01);
		
		mTextDeleteButton = (Button) findViewById(R.id.textDeleteButton);
		mMeButton = (Button) findViewById(R.id.meButton);
		if(Utility.mFacebook.isSessionValid()) {
			mMeButton.setVisibility(View.VISIBLE);
		}
		
		params = new Bundle();
		mSubmitButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				
				
				((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(mInputId.getWindowToken(), 0);
				
				//prepare the URL to be shown on 'View URL' click action. This is not used by the SDK 
				url = BASE_GRAPH_URL; //Base URL
				
				/*
				 * Source Tag: graph_explorer
				 */
				rootString = mInputId.getText().toString();
				if(!TextUtils.isEmpty(rootString)) {
					dialog = ProgressDialog.show(GraphExplorer.this, "", getString(R.string.please_wait), true, true);
					params.putString("metadata", "1");
					Utility.mAsyncRunner.request(rootString, params, new graphApiRequestListener());
					url += "/" + rootString; //Relative Path provided by you
				}
				
				
	        }
	    });
		
		mViewURLButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				setText(url);
				Linkify.addLinks(mOutput, Linkify.WEB_URLS);
			}
		});
		
		mGetPermissionsButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				if(Utility.mFacebook.isSessionValid()) {
					dialog = ProgressDialog.show(GraphExplorer.this, "", getString(R.string.fetching_current_permissions), true, true);
					Bundle params = new Bundle();
					params.putString("access_token", Utility.mFacebook.getAccessToken());
					Utility.mAsyncRunner.request("me/permissions", params, new permissionsRequestListener());
				} else {
					new PermissionsDialog(GraphExplorer.this).show();
				}
			}
		});
		
		mFieldsConnectionsButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				if(metadataObject == null) {
					makeToast("No fields, connections availalbe for this object.");
				} else {
					new FieldsConnectionsDialog(GraphExplorer.this, metadataObject).show();
				}
			}
		});
		
		mTextDeleteButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				url = BASE_GRAPH_URL; //Base URL
				mParentObjectId="";
				mInputId.setText("");
				params.clear();
				metadataObject=null;
				setText("");
				mBackParentButton.setVisibility(View.INVISIBLE);
			}
		});
		
		mMeButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				mInputId.setText("me");
				mSubmitButton.performClick();
			}
		});
		
		mBackParentButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				mInputId.setText(mParentObjectId);
				mParentObjectId = "";
				mSubmitButton.performClick();
			}
		});
	}
	
	public void onResume() {
		super.onResume();
		if(Utility.mFacebook.isSessionValid()) {
			mMeButton.setVisibility(View.VISIBLE);
		}
		if(Utility.objectID != null) {
			mInputId.setText(Utility.objectID);
			Utility.objectID = null;
			mSubmitButton.performClick();
		}
	}
	
    protected void processIntent(Intent incomingIntent) {
        Uri intentUri = incomingIntent.getData();
        if (intentUri == null) {
            return;
        }
        String objectID = intentUri.getHost();
        mInputId.setText(objectID);
		mSubmitButton.performClick();
    }

	public void getConnection(String connection) {
		mInputId.setText(rootString + "/" + connection);
		mParentObjectId = rootString;
		mSubmitButton.performClick();
	}
	
	public void getFields(Vector<String> fieldsVector) {
		String fields = "";
		int count = 0;
		 for (String field : fieldsVector) {
			 fields += field;
			 if(++count < fieldsVector.size()) {
				 fields += ",";
			 }
		 }
		 params.putString("fields", fields);
		 mSubmitButton.performClick();
	}
	
	/*
	 * Callback for the permission OAuth Dialog
	 */
	public class permissionsRequestListener extends BaseRequestListener {

	    public void onComplete(final String response, final Object state) {
	    	dialog.dismiss();
	    	/*
	    	 * clear the current permission list and repopulate with new permissions
	    	 * This is used to mark assigned permission green and unclickable.
	    	 */
	    	Utility.currentPermissions.clear();
			try {
				JSONObject jsonObject = new JSONObject(response).getJSONArray("data").getJSONObject(0);
				Iterator<?> iterator = jsonObject.keys();
				String permission;
				while(iterator.hasNext()) {
					permission = (String)iterator.next();
					Utility.currentPermissions.put(permission, String.valueOf(jsonObject.getInt(permission)));
				}
			} catch (JSONException e) {
				makeToast("Permissions could not be fetched, none will be selected by default.");
			}
			mHandler.post(new Runnable() {
	            public void run() {
	            	new PermissionsDialog(GraphExplorer.this).show();
	            }
			});
	    }
	    
	    public void onFacebookError(FacebookError error) {
	    	dialog.dismiss();
	    	makeToast("Permissions could not be fetched, none will be selected by default.");
	    	mHandler.post(new Runnable() {
	            public void run() {
	            	new PermissionsDialog(GraphExplorer.this).show();
	            }
			});
	    }
	    
	}
	
	@Override
    protected void onActivityResult(int requestCode, int resultCode,
                                    Intent data) {
    	Utility.mFacebook.authorizeCallback(requestCode, resultCode, data);
    }
	
	/*
	 * Callback after a given Graph API request is executed
	 * Get the response and show it.
	 */
	public class graphApiRequestListener extends BaseRequestListener {

	    public void onComplete(final String response, final Object state) {
	    	dialog.dismiss();
	    	//access token is appended by Facebook object, hence params are added here after request is complete
			if(!params.isEmpty()) {
				url += "?" + Util.encodeUrl(params); //Params
			}
			metadataObject = null;
			params.clear();
			try {
	            JSONObject json = Util.parseJson(response);
	            if(json.has("metadata")) {
	            	metadataObject =  json.getJSONObject("metadata");
	            	json.remove("metadata");
	            } else {
	            	metadataObject = null;
	            }
	            setText(json.toString(2));
			} catch (JSONException e) {
				setText(e.getMessage());
				e.printStackTrace();
			} catch (FacebookError e) {
				setText(e.getMessage());
				e.printStackTrace();
			}
	    }
	    
	    public void onFacebookError(FacebookError error) {
	    	dialog.dismiss();
	    	setText(error.getMessage());
			params.clear();
			metadataObject = null;
	    }
	    
	}
	
	public void setText(final String txt) {
		mHandler.post(new Runnable() {
    		
    		/*
    		 * A transform filter that simply returns just the text captured by the
    		 * first regular expression group.
    		 */
    	    TransformFilter idFilter = new TransformFilter() {
    	        public final String transformUrl(final Matcher match, String url) {
    	            return match.group(1);
    	        }
    	    };
    	    
            public void run() {
            	mViewURLButton.setVisibility(TextUtils.isEmpty(txt)? View.INVISIBLE : View.VISIBLE);
            	mFieldsConnectionsButton.setVisibility(TextUtils.isEmpty(txt)? View.INVISIBLE : View.VISIBLE);
            	mOutput.setVisibility(TextUtils.isEmpty(txt)? View.INVISIBLE : View.VISIBLE);
				mBackParentButton.setVisibility(TextUtils.isEmpty(mParentObjectId)? View.INVISIBLE : View.VISIBLE);
            	
            	String convertedTxt = txt.replace("\\/", "/");
            	mOutput.setText(convertedTxt);
            	mScrollView.scrollTo(0, 0);
            	
                
            	Linkify.addLinks(mOutput, Linkify.WEB_URLS);
            	/*
            	 * Linkify the object ids so they can be clicked.
            	 * match pattern: "id" : "objectid" (objectid can be int or int_int)
            	 */
            	Pattern pattern = Pattern.compile("\"id\": \"(\\d*_?\\d*)\"");
                String scheme = "fbGraphEx://";
                Linkify.addLinks(mOutput, pattern, scheme, null, idFilter);
            }
        });
    }
	
	
	private void makeToast(final String msg) {
		mHandler.post(new Runnable() {
            public void run() {
            	Toast.makeText(GraphExplorer.this, msg, Toast.LENGTH_SHORT).show();
            }
		});
	}
}

